package com.lwq.fast.log.fastlogclient.log4j2.appender;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.lwq.fast.log.fastlogclient.log4j2.appender.util.MessageUtil;
import com.lwq.fast.log.fastlogcore.client.redis.RedisClient;
import com.lwq.fast.log.fastlogcore.entity.Message;
import com.lwq.fast.log.fastlogcore.util.ThreadPoolUtil;
import com.lwq.fast.log.fastlogcore.work.MessageCollection;
import org.apache.logging.log4j.core.Filter;
import org.apache.logging.log4j.core.Layout;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.appender.AbstractAppender;
import org.apache.logging.log4j.core.config.Property;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
import org.apache.logging.log4j.core.config.plugins.PluginElement;
import org.apache.logging.log4j.core.config.plugins.PluginFactory;
import org.apache.logging.log4j.core.layout.PatternLayout;

import java.io.Serializable;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * 自定义 appender
 * @author 刘文强
 */
@Plugin(name = "Log4jRedisAppender", category = "Core", elementType = "appender", printObject = true)
public class RedisAppender  extends AbstractAppender {

    /**
     * 应用名称
     */
    private String appName;
    /**
     * 环境信息  如： dev， test, prod 等
     */
    private String env;


    /**
     * redis host
     */
    private String host;
    /**
     * redis port
     */
    private int port;
    /**
     * redis 认证密码
     */
    private String auth;


    protected RedisAppender(String name, Filter filter, Layout<? extends Serializable> layout,
                            boolean ignoreExceptions,  String appName, String env, String host,
                            int port, String auth) {
        super(name, filter, layout, ignoreExceptions, Property.EMPTY_ARRAY);
        this.appName = appName;
        this.env = env;
        this.host = host;
        this.port = port;
        this.auth = auth;
        RedisClient instance = RedisClient.getInstance(host, port, auth);
        if (ObjectUtil.isNotNull(instance)){
            // 从队列中获取消息，发送到 MQ中
            ThreadPoolExecutor threadPoolExecutor = ThreadPoolUtil.getThreadPoolExecutor();
            threadPoolExecutor.execute(() -> {
                MessageCollection.messageCollect(instance);
            });
        }
    }

    @Override
    public void append(LogEvent logEvent) {
        Message message = MessageUtil.formatMessage(appName, env, logEvent);
        if (ObjectUtil.isNotNull(message)){
            MessageCollection.addMessage2Queue(JSON.toJSONString(message));
        }

    }
    @PluginFactory
    public static RedisAppender createAppender(@PluginAttribute("name") String name,
                                                   @PluginElement("filter") Filter filter,
                                                   @PluginElement("layout") Layout<? extends Serializable> layout,
                                                   @PluginAttribute("ignoreExceptions") boolean ignoreExceptions,
                                                   @PluginAttribute("appName") String appName,
                                                   @PluginAttribute("env") String env,
                                                   @PluginAttribute("host") String host,
                                                   @PluginAttribute("port") int port,
                                                   @PluginAttribute("auth") String auth
    ) {
        if (null == name) {
            LOGGER.error("name 为空");
            return null;
        }
        if (null == layout) {
            layout = PatternLayout.createDefaultLayout();
        }
        return new RedisAppender(name, filter, layout, ignoreExceptions, appName, env, host, port, auth);
    }










    public String getAppName() {
        return appName;
    }

    public void setAppName(String appName) {
        this.appName = appName;
    }

    public String getEnv() {
        return env;
    }

    public void setEnv(String env) {
        this.env = env;
    }

    public String getHost() {
        return host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public int getPort() {
        return port;
    }

    public void setPort(int port) {
        this.port = port;
    }

    public String getAuth() {
        return auth;
    }

    public void setAuth(String auth) {
        this.auth = auth;
    }
}
